#include "StdTable.h"

#include "Bridge.h"

StdTable::StdTable(QWidget* parent) : AbstractStdTable(parent) {}

/************************************************************************************
                                   Sorting
************************************************************************************/
bool StdTable::SortBy::AsText(const QString& a, const QString& b) {
  auto i = QString::compare(a, b);
  if (i < 0) return true;
  if (i > 0) return false;
  return duint(&a) < duint(&b);
}

bool StdTable::SortBy::AsInt(const QString& a, const QString& b) {
  if (a.toLongLong() < b.toLongLong()) return true;
  if (a.toLongLong() > b.toLongLong()) return false;
  return duint(&a) < duint(&b);
}

bool StdTable::SortBy::AsHex(const QString& a, const QString& b) {
  if (a.toLongLong(0, 16) < b.toLongLong(0, 16)) return true;
  if (a.toLongLong(0, 16) > b.toLongLong(0, 16)) return false;
  return duint(&a) < duint(&b);
}

/************************************************************************************
                                Data Management
************************************************************************************/
void StdTable::addColumnAt(int width, QString title, bool isClickable,
                           QString copyTitle, SortBy::t sortFn) {
  AbstractTableView::addColumnAt(width, title, isClickable);

  // append empty column to list of rows
  for (size_t i = 0; i < mData.size(); i++) mData[i].push_back(CellData());

  // Append copy title
  if (!copyTitle.length())
    mCopyTitles.push_back(title);
  else
    mCopyTitles.push_back(copyTitle);

  // append column sort function
  mColumnSortFunctions.push_back(sortFn);
}

void StdTable::deleteAllColumns() {
  setRowCount(0);
  AbstractTableView::deleteAllColumns();
  mCopyTitles.clear();
  mColumnSortFunctions.clear();
}

void StdTable::setRowCount(dsint count) {
  int wRowToAddOrRemove = count - int(mData.size());
  for (int i = 0; i < qAbs(wRowToAddOrRemove); i++) {
    if (wRowToAddOrRemove > 0) {
      mData.push_back(std::vector<CellData>());
      for (int j = 0; j < getColumnCount(); j++)
        mData[mData.size() - 1].push_back(CellData());
    } else
      mData.pop_back();
  }
  AbstractTableView::setRowCount(count);
}

void StdTable::setCellContent(int r, int c, QString s) {
  if (isValidIndex(r, c)) mData[r][c].text = std::move(s);
}

QString StdTable::getCellContent(int r, int c) {
  if (isValidIndex(r, c))
    return mData[r][c].text;
  else
    return QString("");
}

void StdTable::setCellUserdata(int r, int c, duint userdata) {
  if (isValidIndex(r, c)) mData[r][c].userdata = userdata;
}

duint StdTable::getCellUserdata(int r, int c) {
  return isValidIndex(r, c) ? mData[r][c].userdata : 0;
}

bool StdTable::isValidIndex(int r, int c) {
  if (r < 0 || c < 0 || r >= int(mData.size())) return false;
  return c < int(mData.at(r).size());
}

void StdTable::sortRows(int column, bool ascending) {
  auto sortFn = mColumnSortFunctions.at(column);
  std::stable_sort(
      mData.begin(), mData.end(),
      [column, ascending, &sortFn](const std::vector<CellData>& a,
                                   const std::vector<CellData>& b) {
        auto less = sortFn(a.at(column).text, b.at(column).text);
        return ascending ? less : !less;
      });
}
